﻿using BW.WMS.WareHouseAllot;
using BW.WMS.WareHouseAllot.Dto;
using BW.WMS.WareHouseAllot.Parameter.Input.GoodsType;
using BW.WMS.WareHouseManage.Dtos;
using BW.WMS.WareHouseManage.IServices;
using BW.WMS.Redis; // 添加Redis服务引用
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;

namespace BW.WMS.WareHouseManage.Services
{
    public class WareHouseManageAppService : ApplicationService, IWareHouseManageAppService
    {
        private readonly IRepository<Warehouse, Guid> warehouseRepository;
        private readonly IRedisService _redisService; // 添加Redis服务

        // Redis缓存键常量
        private const string WAREHOUSE_PAGED_CACHE_KEY = "warehouse:paged:{0}";
        private const string WAREHOUSE_LIST_CACHE_KEY = "warehouse:list";
        private const string WAREHOUSE_DETAIL_CACHE_KEY = "warehouse:detail:{0}";

        public WareHouseManageAppService(
            IRepository<Warehouse, Guid> _warehouseRepository,
            IRedisService redisService) // 注入Redis服务
        {
            warehouseRepository = _warehouseRepository;
            _redisService = redisService;
        }

        /// <summary>
        /// 分页查询仓库列表（带Redis缓存）
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<WarehouseDto>> GetPagedListAsync(PagedWarehouseRequestDto input)
        {
            // 生成缓存键，包含查询条件
            var cacheKey = GeneratePagedCacheKey(input);

            try
            {
                // 尝试从Redis缓存获取数据
                var cachedResult = await _redisService.GetAsync<PagedResultDto<WarehouseDto>>(cacheKey);
                if (cachedResult != null)
                {
                    Logger.LogInformation($"从Redis缓存获取分页仓库列表成功，缓存键: {cacheKey}，总数: {cachedResult.TotalCount}");
                    return cachedResult;
                }

                Logger.LogDebug($"Redis缓存未命中，从数据库查询，缓存键: {cacheKey}");
            }
            catch (Exception ex)
            {
                Logger.LogWarning(ex, $"从Redis获取缓存失败，将从数据库查询，缓存键: {cacheKey}");
            }

            // 缓存中没有数据，从数据库查询
            var query = await warehouseRepository.GetQueryableAsync();

            // 应用查询条件
            if (!string.IsNullOrWhiteSpace(input.Name))
            {
                query = query.Where(x => x.Name.Contains(input.Name));
            }
            if (!string.IsNullOrWhiteSpace(input.Address))
            {
                query = query.Where(x => x.Address.Contains(input.Address));
            }

            var totalCount = await query.CountAsync();

            var items = await query
                .OrderByDescending(x => x.Code)
                .Skip(input.SkipCount)
                .Take(input.MaxResultCount)
                .ToListAsync();

            var result = new PagedResultDto<WarehouseDto>(
                totalCount,
                ObjectMapper.Map<List<Warehouse>, List<WarehouseDto>>(items)
            );

            // 将查询结果存入Redis缓存
            await CachePagedResult(cacheKey, result);

            Logger.LogInformation($"从数据库查询仓库分页列表完成，总数: {totalCount}，当前页: {items.Count}");

            return result;
        }

        /// <summary>
        /// 创建仓库
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<WarehouseDto> CreateWarehouse(AddWarehouseDto input)
        {
            var warehouse = ObjectMapper.Map<AddWarehouseDto, Warehouse>(input);
            warehouse.Code = "WareHouse" + DateTime.Now.ToString("yyyyMMdd") + (await warehouseRepository.GetCountAsync()).ToString("D4");

            await warehouseRepository.InsertAsync(warehouse);

            // 处理库区关联
            if (input.ZoneIds != null && input.ZoneIds.Any())
            {
                var zoneRepository = LazyServiceProvider.LazyGetRequiredService<IRepository<Zone, Guid>>();

                foreach (var zoneId in input.ZoneIds)
                {
                    var zone = await zoneRepository.GetAsync(zoneId);
                    if (zone != null)
                    {
                        zone.WarehouseId = warehouse.Id;
                        await zoneRepository.UpdateAsync(zone);
                    }
                }
            }

            // 清除相关缓存
            await ClearWarehouseCaches();

            Logger.LogInformation($"创建仓库成功，ID: {warehouse.Id}，Code: {warehouse.Code}，已清除相关缓存");

            return ObjectMapper.Map<Warehouse, WarehouseDto>(warehouse);
        }

        /// <summary>
        /// 删除仓库
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task DeleteAsync(Guid id)
        {
            var warehouse = await warehouseRepository.GetAsync(id);
            if (warehouse == null)
            {
                throw new UserFriendlyException("仓库不存在");
            }

            await warehouseRepository.DeleteAsync(warehouse);

            // 清除相关缓存
            await ClearWarehouseCaches();
            await ClearWarehouseDetailCache(id);

            Logger.LogInformation($"删除仓库成功，ID: {id}，已清除相关缓存");
        }

        /// <summary>
        /// 更新仓库信息
        /// </summary>
        /// <param name="id"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<WarehouseDto> UpdateAsync(Guid id, UpdateWarehouseDto input)
        {
            var warehouse = await warehouseRepository.GetAsync(id);
            if (warehouse == null)
            {
                throw new UserFriendlyException("仓库不存在");
            }

            // 更新仓库属性
            warehouse.Name = input.Name;
            warehouse.Address = input.Address;
            warehouse.Status = input.Status;
            warehouse.ContactPerson = input.ContactPerson;
            warehouse.ContactPhone = input.ContactPhone;
            warehouse.Area = input.Area;
            warehouse.Description = input.Description;
            warehouse.WarehouseType = input.WarehouseType;
            warehouse.Manager = input.Manager;
            warehouse.Department = input.Department;
            warehouse.SortOrder = input.SortOrder;
            warehouse.IsQuickSelect = input.IsQuickSelect;

            await warehouseRepository.UpdateAsync(warehouse);

            // 清除相关缓存
            await ClearWarehouseCaches();
            await ClearWarehouseDetailCache(id);

            var result = ObjectMapper.Map<Warehouse, WarehouseDto>(warehouse);

            Logger.LogInformation($"更新仓库成功，ID: {id}，已清除相关缓存");

            return result;
        }

        /// <summary>
        /// 根据仓库ID获取仓库详情（带Redis缓存）
        /// </summary>
        /// <param name="id">仓库ID</param>
        /// <returns>仓库DTO</returns>
        public async Task<WarehouseDto> GetByCodeAsync(Guid id)
        {
            var cacheKey = string.Format(WAREHOUSE_DETAIL_CACHE_KEY, id);

            try
            {
                // 尝试从Redis缓存获取
                var cachedResult = await _redisService.GetAsync<WarehouseDto>(cacheKey);
                if (cachedResult != null)
                {
                    Logger.LogInformation($"从Redis缓存获取仓库详情成功，ID: {id}");
                    return cachedResult;
                }

                Logger.LogDebug($"仓库详情缓存未命中，从数据库查询，ID: {id}");
            }
            catch (Exception ex)
            {
                Logger.LogWarning(ex, $"从Redis获取仓库详情缓存失败，ID: {id}");
            }

            // 从数据库查询
            var warehouse = await warehouseRepository.GetAsync(id);
            var result = ObjectMapper.Map<Warehouse, WarehouseDto>(warehouse);

            // 查询关联的库区
            var zoneRepository = LazyServiceProvider.LazyGetRequiredService<IRepository<Zone, Guid>>();
            var zones = await zoneRepository.GetListAsync(z => z.WarehouseId == id);
            result.Zones = ObjectMapper.Map<List<Zone>, List<ZoneDto>>(zones);

            // 存入缓存，30分钟过期
            await CacheWarehouseDetail(cacheKey, result);

            Logger.LogInformation($"从数据库查询仓库详情完成，ID: {id}，库区数量: {zones.Count}");

            return result;
        }

        /// <summary>
        /// 获取仓库列表（带Redis缓存）
        /// </summary>
        /// <returns></returns>
        public async Task<List<WarehouseDto>> GetWarehouseListAsync()
        {
            try
            {
                // 尝试从缓存获取
                var cachedList = await _redisService.GetAsync<List<WarehouseDto>>(WAREHOUSE_LIST_CACHE_KEY);
                if (cachedList != null && cachedList.Any())
                {
                    Logger.LogInformation($"从Redis缓存获取仓库列表成功，数量: {cachedList.Count}");
                    return cachedList;
                }

                Logger.LogDebug("仓库列表缓存未命中，从数据库查询");
            }
            catch (Exception ex)
            {
                Logger.LogWarning(ex, "从Redis获取仓库列表缓存失败");
            }

            // 从数据库查询
            var warehouses = await warehouseRepository.GetListAsync(w => w.Status == 1);

            var result = warehouses.Select(w => new WarehouseDto
            {
                Id = w.Id,
                Name = w.Name
            }).ToList();

            // 存入缓存，1小时过期
            await CacheWarehouseList(result);

            Logger.LogInformation($"从数据库查询仓库列表完成，数量: {result.Count}");

            return result;
        }

        /// <summary>
        /// 批量删除仓库
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<BatchDeleteResultDto> BatchDeleteAsync(List<Guid> ids)
        {
            var result = new BatchDeleteResultDto();
            if (ids == null || !ids.Any())
            {
                return result;
            }

            foreach (var id in ids)
            {
                var warehouse = await warehouseRepository.GetAsync(id);
                await warehouseRepository.DeleteAsync(id);
                result.SuccessCount++;

                // 清除单个仓库的详情缓存
                await ClearWarehouseDetailCache(id);
            }

            // 清除列表缓存
            await ClearWarehouseCaches();

            Logger.LogInformation($"批量删除仓库成功，数量: {result.SuccessCount}，已清除相关缓存");

            return result;
        }

        #region 私有方法 - 缓存管理

        /// <summary>
        /// 生成分页查询的缓存键
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private string GeneratePagedCacheKey(PagedWarehouseRequestDto input)
        {
            var keyBuilder = new StringBuilder();
            keyBuilder.Append($"name:{input.Name ?? "null"}");
            keyBuilder.Append($"|address:{input.Address ?? "null"}");
            keyBuilder.Append($"|skip:{input.SkipCount}");
            keyBuilder.Append($"|take:{input.MaxResultCount}");

            var cacheKey = string.Format(WAREHOUSE_PAGED_CACHE_KEY, keyBuilder.ToString());
            return cacheKey;
        }

        /// <summary>
        /// 缓存分页查询结果
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        private async Task CachePagedResult(string cacheKey, PagedResultDto<WarehouseDto> result)
        {
            try
            {
                // 分页数据缓存10分钟，因为数据可能变化较频繁
                await _redisService.SetAsync(cacheKey, result, TimeSpan.FromMinutes(10));
                Logger.LogDebug($"分页查询结果已存入Redis缓存，缓存键: {cacheKey}");
            }
            catch (Exception ex)
            {
                Logger.LogWarning(ex, $"缓存分页查询结果失败，缓存键: {cacheKey}");
            }
        }

        /// <summary>
        /// 缓存仓库详情
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        private async Task CacheWarehouseDetail(string cacheKey, WarehouseDto result)
        {
            try
            {
                // 仓库详情缓存30分钟
                await _redisService.SetAsync(cacheKey, result, TimeSpan.FromMinutes(30));
                Logger.LogDebug($"仓库详情已存入Redis缓存，缓存键: {cacheKey}");
            }
            catch (Exception ex)
            {
                Logger.LogWarning(ex, $"缓存仓库详情失败，缓存键: {cacheKey}");
            }
        }

        /// <summary>
        /// 缓存仓库列表
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        private async Task CacheWarehouseList(List<WarehouseDto> result)
        {
            try
            {
                // 仓库列表缓存1小时
                await _redisService.SetAsync(WAREHOUSE_LIST_CACHE_KEY, result, TimeSpan.FromHours(1));
                Logger.LogDebug($"仓库列表已存入Redis缓存，数量: {result.Count}");
            }
            catch (Exception ex)
            {
                Logger.LogWarning(ex, "缓存仓库列表失败");
            }
        }

        /// <summary>
        /// 清除仓库相关的所有缓存（简化版本）
        /// </summary>
        private async Task ClearWarehouseCaches()
        {
            try
            {
                // 清除仓库列表缓存
                await _redisService.RemoveAsync(WAREHOUSE_LIST_CACHE_KEY);

                // 由于无法使用模式删除，这里手动清除常见的分页缓存
                // 实际项目中建议维护一个缓存键的集合
                var commonPagedKeys = new List<string>
                {
                    string.Format(WAREHOUSE_PAGED_CACHE_KEY, "name:null|address:null|skip:0|take:10"),
                    string.Format(WAREHOUSE_PAGED_CACHE_KEY, "name:null|address:null|skip:0|take:20"),
                    string.Format(WAREHOUSE_PAGED_CACHE_KEY, "name:null|address:null|skip:0|take:50"),
                    // 可以添加更多常见的查询条件组合
                };

                await _redisService.RemoveMultipleAsync(commonPagedKeys);

                Logger.LogInformation("已清除仓库相关缓存");
            }
            catch (Exception ex)
            {
                Logger.LogWarning(ex, "清除仓库缓存时发生错误");
            }
        }

        /// <summary>
        /// 清除单个仓库详情缓存
        /// </summary>
        /// <param name="warehouseId"></param>
        private async Task ClearWarehouseDetailCache(Guid warehouseId)
        {
            try
            {
                var cacheKey = string.Format(WAREHOUSE_DETAIL_CACHE_KEY, warehouseId);
                await _redisService.RemoveAsync(cacheKey);

                Logger.LogDebug($"已清除仓库详情缓存，ID: {warehouseId}");
            }
            catch (Exception ex)
            {
                Logger.LogWarning(ex, $"清除仓库详情缓存时发生错误，ID: {warehouseId}");
            }
        }

        #endregion

        #region 缓存管理和监控方法

        /// <summary>
        /// 预热仓库缓存
        /// </summary>
        public async Task WarmupCacheAsync()
        {
            try
            {
                Logger.LogInformation("开始预热仓库缓存...");

                // 预热仓库列表
                await GetWarehouseListAsync();

                // 预热前10个仓库的详情
                var warehouses = await warehouseRepository.GetListAsync();
                var topWarehouses = warehouses.Take(10);

                foreach (var warehouse in topWarehouses)
                {
                    await GetByCodeAsync(warehouse.Id);
                }

                Logger.LogInformation("仓库缓存预热完成");
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "预热仓库缓存时发生错误");
            }
        }

        /// <summary>
        /// 获取缓存统计信息
        /// </summary>
        public async Task<object> GetCacheStatsAsync()
        {
            try
            {
                var stats = new
                {
                    WarehouseListCacheExists = await _redisService.ExistsAsync(WAREHOUSE_LIST_CACHE_KEY),
                    CacheKeyPrefix = "warehouse:",
                    // 可以添加更多统计信息
                };

                return stats;
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "获取缓存统计信息时发生错误");
                return new { Error = "获取缓存统计失败" };
            }
        }

        #endregion
    }
}